#ifndef NR_NET_SERVER_LOGIC
#define NR_NET_SERVER_LOGIC

#include "nr_std.h"
#include "nr_net_command.h"
#include "nr_object.h"
#include "nr_object_manager.h"
#include "nr_net_socket.h"
#include "nr_io_manager.h"
#include <QByteArray>

typedef QHash<nr_device_id_t, nr_channel_output*> nr_session_channels;

class nr_net_session : public nr_channel_output_delegate
{
public:
    nr_net_session(nr_channel_manager &channel_manager);
    ~nr_net_session();

    nr_id_t& session_id() { return m_session_id; }
    nr_session_channels& channels() { return m_channels; }
    nr_net_socket*& socket() { return m_socket; }
    
    bool is_empty() { return m_channels.empty(); }
    void stop_device(const nr_device_id_t& device_id);
    void close();

    // nr_channel_output interfaces
    virtual void on_data(nr_data *data);
    virtual void on_event(nr_event *evt);
    
private:
    
    nr_id_t m_session_id;
    nr_session_channels m_channels;
    nr_net_socket *m_socket;
    nr_channel_manager &m_channel_manager;
};

typedef QHash<nr_id_t, nr_net_session*> nr_net_sessions;

class nr_net_server_logic : public QObject
{
    Q_OBJECT
public:
    nr_net_server_logic(nr_object_manager& object_manager);
    ~nr_net_server_logic(void);
    
    bool execute(nr_net_socket &socket, nr_net_command_header &request_header, QByteArray &request_byte_array,
        nr_net_command_header &reply_header, QByteArray &reply_byte_array);
    
    void close_session(nr_id_t& session_id);

private:
    void remove_session_if_empty(nr_net_session *session);

    nr_error_t on_login(nr_net_socket &socket, nr_object &request, nr_object &reply);
    nr_error_t on_logout(nr_net_socket &socket, nr_object &request, nr_object &reply);
    nr_error_t on_get_items(nr_net_socket &socket, nr_object &request, nr_object  &reply);
    nr_error_t on_start_data(nr_net_socket &socket, nr_object &request, nr_object &reply);
    nr_error_t on_stop_data(nr_net_socket &socket, nr_object &request, nr_object &reply);
    nr_error_t on_query(nr_net_socket &socket, nr_object &request, nr_object &reply);
    
    nr_object_manager& m_object_manager;
    nr_net_sessions m_sessions;
    nr_io_manager m_io_manager;
};

#endif